---
slug: /ci/quickstart/env
title: "Create the build environment"
---
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";

# Dagger for CI: Quickstart

## Create the build environment

You're now ready to dive into Dagger and see how Dagger Functions work!

In the example pipeline you just ran, the `publish` stage depends on the `test` and `build` stages, which in turn depend on the `build-env` stage. Dagger represents these stages and dependencies in a [Directed Acyclic Graph (DAG)](https://en.wikipedia.org/wiki/Directed_acyclic_graph), which it then runs concurrently to maximize pipeline speed and accuracy.

Let's start with the `build-env` stage and look at its Dagger Function first.

### Inspect the Dagger Function

<Tabs groupId="language">
<TabItem value="Go">

```go file=./snippets/env/go/main.go
```

</TabItem>
<TabItem value="Python">

```python file=./snippets/env/python/__init__.py
```

</TabItem>
<TabItem value="TypeScript">

```typescript file=./snippets/env/typescript/index.ts
```

</TabItem>
<TabItem value="PHP">

```php file=./snippets/env/php/src/HelloDagger.php
```

</TabItem>
<TabItem value="Java">

```java file=./snippets/env/java/src/main/java/io/dagger/modules/hellodagger/HelloDagger.java
```

</TabItem>
</Tabs>

This Dagger Function expects a `source` argument of type `Directory`. This argument tells the Dagger Function where to find the application's source code, and may refer to either a local directory or a remote Git repository.

The Dagger Function begins by calling the `dag` client, which is pre-initialized in every Dagger Function. This client contains all the core types (like `Container`, `Directory`, etc.), as well as bindings to any dependencies your module has declared.

It uses the `dag` client to initialize a base container from the `node:21-slim` image as a `Container` object. This `Container` object comes with useful methods of its own, which are then called in a chain to add source code to the container, configure a cache volume and run `npm install` to install dependencies (refer to the code comments for details).

:::tip FUNCTION CHAINING
If you've worked with Dockerfiles, this Dagger Function should look very familiar to you. Similar to the instructions in a Dockerfile, it starts with a base container image, then calls various functions to revise the base image. The base image is represented as a `Container` object, which is one of Dagger's core types. The Dagger API lets you manipulate the container by calling the object's functions, which can then return another object, and so on. This is called ["chaining"](../../features/programmable-pipelines.mdx), and is a core feature of Dagger.
:::

### Call the Dagger Function

Now that you know how the Dagger Function works, call it as below:

```shell
dagger call build-env --source=.
```

Here's what you should see:

![Build env](/img/current_docs/quickstart/buildenv.gif)

This output means that the build succeeded, and a `Container` type representing the built container image was returned. This is a ["just-in-time container"](../../features/programmable-pipelines.mdx) - a transient artifact produced as the result of a Dagger Function.

:::tip FUNCTION NAMES
When using `dagger call`, all names (functions, arguments, fields, etc.) are converted into a shell-friendly "kebab-case" style. This is why Dagger Functions named `FooBar` in Go, `foo_bar` in Python and `fooBar` in TypeScript/PHP/Java are called with `dagger call foo-bar ...`.
:::

### Interact with a just-in-time container

Just-in-time containers come with useful functions of their own, which you can call by chaining them to the artifact in the `dagger call` command. One of the most interesting functions is `terminal`, which can be used to [open an interactive terminal session with the running container](../../features/debugging.mdx).

To see this in action, chain an additional function call to `terminal` on the returned `Container`:

```shell
dagger call \
  build-env --source=. \
  terminal --cmd=bash
```

This command builds the container image and then drops you into an interactive terminal running the `bash` shell. You can now directly execute commands in the running container, as shown below:

![Build env with terminal](/img/current_docs/quickstart/buildenv-terminal.gif)

:::tip INTERACTIVE CONTAINER DEBUGGING
The `terminal` function is very useful for debugging and experimenting, since it allows you to interact directly with containers and inspect their state, at any stage of your Dagger Function execution.
:::
